﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Text;
using System.Net;
using System.IO;
using Quartz;
using Quartz.Impl;
using System.Web.Hosting;
/// <summary>
/// CronService 的摘要说明
/// </summary>
public class CronService : IRegisteredObject
{
    private readonly object _lock = new object();

    private bool _started = false;

    private CronService()
    {
        HostingEnvironment.RegisterObject(this);
    }

    private static CronService _instance = null;

    public static CronService Instance
    {
        get
        {
            if (_instance == null)
                _instance = new CronService();
            
            return _instance;
        }
    }

    private IScheduler _scheduler = null;

    public IScheduler Scheduler
    {
        get
        {
            if (_scheduler == null)
            {
                ISchedulerFactory schedulerFactory = new StdSchedulerFactory();
                IScheduler scheduler = schedulerFactory.GetScheduler();

                _scheduler = scheduler;
            }
            return _scheduler;
        }
    }
    

    public void Start()
    {
        
        lock (_lock)
        {
            if (_started)
                return;

            _started = true;

            Maticsoft.BLL.bll_api bll = new Maticsoft.BLL.bll_api();
            DataTable dt = bll.GetAllList().Tables[0];

            foreach (DataRow row in dt.Rows)
            {
                GMS.Core.Config.UrlInfo urlInfo = new GMS.Core.Config.UrlInfo();

                urlInfo.Id = row["id"].ToString();
                urlInfo.Name = row["apiname"] as string;
                urlInfo.Ready = bool.Parse(row["isusing"].ToString());

                if (!urlInfo.Ready)
                    continue;

                urlInfo.Schedule = row["apimemo"] as string;
                urlInfo.Url = row["apiurl"] as string;
                urlInfo.ContentType = row["contenttype"] as string;
                urlInfo.Content = row["content"] as string;
                urlInfo.HttpMethod = row["httpmethod"] as string;

                IJobDetail jobDetail = JobBuilder.Create<HttpJob>()
               .WithIdentity("Job" + urlInfo.Id)
               .Build();

                jobDetail.JobDataMap.Add("UrlInfo", urlInfo);

                ITrigger trigger = TriggerBuilder.Create()
                    .ForJob(jobDetail)
                    .WithCronSchedule(urlInfo.Schedule)
                    .WithIdentity("Trigger" + urlInfo.Id)
                    .StartNow()
                    .Build();


                this.Scheduler.ScheduleJob(jobDetail, trigger);
                this.Scheduler.Start();
            }
        }


    }

    public void Stop(bool immediate)
    {
        lock (_lock)
        {   
            _started = false;

            this.Scheduler.Clear();
        }
        _instance = null;
        HostingEnvironment.UnregisterObject(this);
    }


    /// <summary>
    /// 重新启动
    /// </summary>
    public void Restart()
    {   
        this.Stop(true);

        this.Start();
    }




    public class HttpJob : IJob, IRegisteredObject
    {
        public HttpJob()
        {   
            HostingEnvironment.RegisterObject(this);
        }

        public static int timeoutSecond = int.Parse(System.Configuration.ConfigurationManager.AppSettings["timeoutSecond"]);

        public void Execute(IJobExecutionContext context)
        {
            var ui = context.JobDetail.JobDataMap.Get("UrlInfo") as GMS.Core.Config.UrlInfo;

            try
            {
                if (ui.HttpMethod.ToLower().Equals("get"))
                {
                    var result = HttpGet(ui.Url, string.Empty, ui.ContentType);

                    GMS.Core.Log.Log4NetHelper.LogInput(GMS.Core.Log.Log4NetHelper.LogType.Timed,"调用API正常", ui.Name, ui.Url, ui.HttpMethod, result);
                }
                else if (ui.HttpMethod.ToLower().Equals("post"))
                {
                    var result = HttpPost(ui.Url, ui.Content, ui.ContentType);

                    GMS.Core.Log.Log4NetHelper.LogInput(GMS.Core.Log.Log4NetHelper.LogType.Timed, "调用API正常", ui.Name, ui.Url, ui.HttpMethod, result);
                }
            }
            catch (Exception ex)
            {
                GMS.Core.Log.Log4NetHelper.LogErrorInput(GMS.Core.Log.Log4NetHelper.LogType.Timed, ex, "调用API异常", ui.Name, ui.Url, ui.HttpMethod);
            }
        }

        public static string HttpGet(string Url, string postDataStr, string contentType)
        {   
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url + (postDataStr == "" ? "" : "?") + postDataStr);
            request.Method = "GET";
            request.ContentType = contentType;
            request.Timeout = 1000 * timeoutSecond;
            
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            Stream myResponseStream = response.GetResponseStream();
            StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.UTF8);
            string retString = myStreamReader.ReadToEnd();
            myStreamReader.Close();
            myResponseStream.Close();

            return retString;
        }


        public static string HttpPost(string Url, string postData, string contentType)
        {
            HttpWebRequest webrequest = (HttpWebRequest)HttpWebRequest.Create(Url);
            webrequest.Method = "POST";
            webrequest.Timeout = 1000 * timeoutSecond;

            byte[] postdatabyte = Encoding.UTF8.GetBytes(postData);
            webrequest.ContentType = contentType;

            webrequest.ContentLength = postdatabyte.Length;
            Stream stream;
            stream = webrequest.GetRequestStream();
            stream.Write(postdatabyte, 0, postdatabyte.Length);
            stream.Close();

            using (var httpWebResponse = webrequest.GetResponse())
            using (StreamReader responseStream = new StreamReader(httpWebResponse.GetResponseStream()))
            {
                String ret = responseStream.ReadToEnd();

                return ret;
            }
        }
        
        public void Stop(bool immediate)
        {   
            HostingEnvironment.UnregisterObject(this);
        }

    }


}